'use strict';

/*
 * @Description: 采用 Node + Express部署的简易后端接口服务器
 * @Author: Mr.Wen
 * @Version: v2.0.0
 * @Date: 2021-11-29 15:19:16
 * @LastEditors: Mr.Wen - 文先生
 * @LastEditTime: 2022-12-17 17:56:56
 */

const express = require('express'); // 轻量级 Web应用
const bodyParser = require('body-parser'); // post 处理提交数据 (为了查看post请求里面的body参数)
const cors = require('cors'); // 配置解决跨域问题
const path = require('path'); // 操作路径
const fs = require('fs'); // 操作文件
const os = require('os'); // 操作系统
const jwt = require('jsonwebtoken');
const app = express(); // 创建 express 服务器实例

/** ****************** 全局token验证 start ****************** **/

app.use(function (req, res, next) {
  // 获取当前访问的API地址
  let orUri = req.originalUrl;

  // 不需要验证的API
  let urlArray = ['/www-service/web/login'];

  if (urlArray.find((item) => item === orUri)) {
    next();
    return;
  }

  //  获取前端 headers传递过来的值
  const { token = '', id_id = '' } = req.headers;

  switch (true) {
    case token === '':
      return res.status(401).json({
        msg: 'token缺少了',
      });
    case id_id === '':
      return res.status(401).json({
        msg: '没登录',
      });
    default:
  }

  // 当token失效过期返回提示信息
  // async function verifyToken(token) {
  //   await jwt.verify(token, 'miyaokey', err => {
  //     if (err) {
  //       res.send({
  //         msg: "同"
  //       })
  //     }
  //   })
  // }
  // verifyToken(token.split(' ')[1])

  jwt.verify(token.split(' ')[1], 'miyaokey', (err) => {
    if (err) {
      res.send({
        msg: '令牌已过期，请重新登录',
        code: 403,
      });
      return;
    }
  });

  // 判断是否有登录
  fs.readFile(path.join('field', 'users.json'), 'utf-8', (err, data) => {
    if (!err) {
      let fields = JSON.parse(data.toString());
      let result = fields.find((item) => item.id_id === id_id);
      if (!result) {
        return res.status(401).json({
          msg: '请先登录',
        });
      } else {
        next();
      }
    }
  });
});

/** ****************** 全局token验证 end ****************** **/

/** ****************** 处理post请求数据(body) start ****************** **/

// 设置 Content-Type属性 用于修改和设定中间件解析的body类容类型。

/** 请求体参数是JSON结构 {name:Tom,pwd:123} (application/json  加上就返回 JSON 否则返回的是数据流) */
// app.use(express.json());
/** 请求体参数是 name=Tom&pwd=123 (application/x-www-form-urlencoded  当为 false,键值对中的值为 'String' 或 'Array' 形式；为 true,则为任何类型数据) */
// app.use(express.urlencoded({ extended: false }));

// 配置解析表单数据的中间件
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

// ***备注：要在引入路由之前，挂载

/** ****************** 处理post请求数据(body) end ****************** **/

/** ****************** 引入路由 start ****************** **/

// 引入路由文件
const TestOld = require('../routes/test/test.old');
const TestNew = require('../routes/test/test.new');

/** routes/test/test.old.js */
app.post('/getMusic', TestOld.Music);
app.get('/getMovie', TestOld.Movie);

/** routes/test/test.new.js */
app.use(TestNew);

/** 升级版本 */
// 引入路由文件(接口)
// const loginService = require('./routes/login.service');
// const userService = require('./routes/user.service');

// app.use('/www-service', [loginService, userService]);

/** 升级版本-自动化 */

fs.readdir('./routes/services', (err, files) => {
  let routeArray = [];
  if (!err) {
    files.forEach((item) => {
      routeArray.push(require(`./routes/services/${item}`));
    });
    app.use('/www-service', routeArray);
  }
});

/** 升级版本-模块化(暂时有问题，后面会优化) */
// routeService('../routes/services', 'www-service');

/** ****************** 引入路由 end ****************** **/

/** ****************** 解决跨域 start ****************** **/

// 注意：html测试代码(测试时注意勾选 F12-Network-Disable cache)

// 方法1：CORS解决跨域
app.use(cors());

// 方法2：中间件-解决跨域
// app.use('/*', (req, res, next) => { // 开发环境使用，生产环境慎用
//   res.header('Access-Control-Allow-Origin', '*'); // 自定义中间件，设置跨域需要的响应头 (允许任何域名跨域)
//   res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS'); // 允许跨域的请求方式 (允许任何方法)
//   res.setHeader('Access-Control-Allow-Headers', 'X-Requested-Width,content-type,X-Session-Token'); // 允许 header 类型跨域 (允许任何类型)
//   res.header("Content-Type", "application/json;charset=utf-8"); // 这段仅仅为了方便返回 json而已
//   next(); // 要添加此代码，不然程序无法正常执行
// })

/** ****************** 解决跨域 end ****************** **/

/** ****************** 配置静态资源 start ****************** **/

// 可通过 http://localhost:2021/static/1.jpg 访问 static中文件

/** 青铜 */
// app.use(express.static("./static"));

/** 王者 */
app.use('/static', express.static(`${__dirname}/static`)); // 指定加载前缀静态资源

/** 白金 */
// app.use('/public', express.static(__dirname + '/public'));
app.use('/public', express.static(path.join(__dirname, 'public')));

/** ****************** 配置静态资源 end ****************** **/

/* ****************** 监听端口程序 start ****************** */

// 获取当前机器 IP 地址
function GetNativeIP() {
  const interfaces = os.networkInterfaces();
  // for (let devName in interfaces) {
  //   for (let i = 0; i < interfaces[devName].length; i++) {
  //     let alias = interfaces[devName][i];
  //     if (alias.family === "IPv4" && alias.address !== '127.0.0.1' && !alias.internal) {
  //       return alias.address;
  //     }
  //   }
  // }

  let localInfo = interfaces['WLAN'].find((v) => v.family === 'IPv4');
  return localInfo.address;
}

// 监听端口
const PORT = process.env.SERVICE_PORT || new Date().getFullYear();
const HOST = 'localhost' || '127.0.0.1' || GetNativeIP();

app.listen(PORT, HOST, () =>
  console.log(
    '\x1B[32m%s\x1B[0m',
    `The Server Is Running On http://${HOST}:${PORT}`
  )
);

/* ****************** 监听端口程序 end ****************** */
